#include "FractalTree.h"

FractalTree::FractalTree(){
	Reset();

}

void FractalTree::Reset(){
	mName = new string("Explosion");
	mPos = new D3DXVECTOR3(0,0,0);
	mExpandRate = 2.0f;// 2.0f* Random();
	mDecayRate = 2.0f;//* Random() + 0.4f;
	mPower = 7.0f;// * Random();
	mSpawnScale = 0.8f;//0.2f* Random() + 0.69f;
	minSize = 0.5f;
	ini = false;
	mNodes= new vector<ExplosionNode*> ();
	mTemp = new vector<ExplosionNode*> ();
	mDone= false;
	mDelay = 300;
	srand(time(0)); 
	mMaxDepth = 1;
}

void FractalTree::Update(float pElapsed){
	mTemp->clear();

	if(!ini){
		ExplosionNode* mHead = new ExplosionNode();
		mHead->Spawned = false;
		mHead->Pos = CalcNewNode(mPos,mPower);
		mHead->Sphere = MakeNewExplosionNode();
		mHead->Sphere->center = *(mHead->Pos);
		mHead->mPower = mPower;
		mHead->Radius = minSize;
		mHead->Expanding = true;
		mHead->Fini = false;
		mHead->Delay = (mDelay) *Random();
		mHead->SmokeDiv =0.0f;
		mNodes->push_back(mHead);

		ini = true;
	}
	else{
		bool done = true;
		for(int i =0; i < mNodes->size(); i++){
			ExplosionNode* mCurrent = mNodes->at(i);
			if(!mCurrent->Fini){
					done =false;
				//Create new explosions
				if(!mCurrent->Spawned){
					mCurrent->Delay += pElapsed;
					int amount = 0;
					if(mCurrent->Delay > mDelay){
						amount = Random() *(mMaxDepth*Random())+1;
						mCurrent->Spawned = true;
					}
					
					ExplosionNode* mNew;
					for(int j = 0; j < amount; j++){
						 mNew = new ExplosionNode();	
						 mNew->mPower = mCurrent->mPower* mSpawnScale;
						 mNew->Radius = minSize;
						 mNew->Pos = CalcNewNode(mCurrent->Pos,mNew->mPower);
						 mNew->SmokeDiv =0.0f;
						 mNew->Expanding = true;
						 if(mNew->mPower >mPower*0.3){
							mNew->Sphere = MakeNewExplosionNode();
							mNew->Sphere->center = *(mNew->Pos);
							mNew->Delay = (mDelay) * Random();
							mNew->Fini = false;
							mNew->Spawned = false;
							mTemp->push_back(mNew);
						 } 
					}
				}

				if(mCurrent->Expanding){
					mCurrent->Radius += pElapsed/1000.0f*mExpandRate*mCurrent->mPower;//*mCurrent->mPower;
					if(mCurrent->Radius >= mCurrent->mPower){
						mCurrent->Expanding = false;
						mCurrent->Radius = mCurrent->mPower;
					}
				}else
				{
					mCurrent->Radius -= pElapsed/1000*mDecayRate*(mCurrent->mPower); //  *(mCurrent->Radius/mCurrent->mPower );
					if(mCurrent->Radius <= 0.0f){
						mCurrent->Radius = 0.0f;
						mCurrent->Fini = true;
					}
				}
				
				mCurrent->Sphere->noiseOffset.x += 0.05f;
				mCurrent->Sphere->noiseOffset.y += 0.05f;
				mCurrent->Sphere->noiseOffset.z += 0.05f;
						
				mCurrent->Sphere->radius = mCurrent->Radius;
				mCurrent->Sphere->center = *(mCurrent->Pos);
				/*
				mCurrent->Sphere->diffuseColor.g = mCurrent->Radius/mCurrent->mPower *255;
				mCurrent->Sphere->diffuseColor.r = 255;
				mCurrent->Sphere->diffuseColor.b = 0;
				mCurrent->Sphere->specularColor.g = mCurrent->Radius/mCurrent->mPower*255;
				mCurrent->Sphere->specularColor.r = 255;
				mCurrent->Sphere->specularColor.b = 0;(
				*/
				mCurrent->Sphere->color.r =1.0f;
				mCurrent->Sphere->color.b =0.0f;
				mCurrent->Sphere->color.g = mCurrent->Radius/mCurrent->mPower;
			}
			mDone = done;
		}

		for(int a=0; a < mTemp->size(); a++){
			mNodes->push_back(mTemp->at(a));
		}
	}
}


D3DXVECTOR3* FractalTree::CalcNewNode(D3DXVECTOR3* pos, float power){
	D3DXVECTOR3* mRet = new D3DXVECTOR3();
	float neg;
	mRet->x = Random() * power;
	neg = Random();

	if(neg > 0.5){
		mRet->x = mRet->x * -1.0f;
	}

	mRet->x += pos->x ;

	mRet->y = Random() * power;

		neg = Random();

	if(neg > 0.5){
		mRet->y = mRet->y * -1.0f;
	}
	mRet->y += pos->y ;

	mRet->z = Random() * power;
	
	neg = Random();

	if(neg > 0.5){
		mRet->z = mRet->z * -1.0f;
	}
	mRet->z += pos->z ;

	return mRet;
}

void FractalTree::Draw(LPDIRECT3DDEVICE9 d3ddev){

		
/*		
		prim->GetMaterial()->Diffuse.g = mCur->Radius/mCur->mPower /mCur->SmokeDiv ;
		prim->GetMaterial()->Ambient.g =  mCur->Radius/mCur->mPower /mCur->SmokeDiv ;
		prim->GetMaterial()->Specular.g =  mCur->Radius/mCur->mPower/mCur->SmokeDiv ;
		prim->GetMaterial()->Emissive.g =  mCur->Radius/mCur->mPower /mCur->SmokeDiv ;

		prim->GetMaterial()->Diffuse.r =   mCur->Radius/mCur->mPower /mCur->SmokeDiv ;
		prim->GetMaterial()->Ambient.r =  mCur->Radius/mCur->mPower/mCur->SmokeDiv  ;
		prim->GetMaterial()->Specular.r =  mCur->Radius/mCur->mPower/mCur->SmokeDiv ;
		prim->GetMaterial()->Emissive.r = mCur->Radius/mCur->mPower/mCur->SmokeDiv ;

		prim->GetMaterial()->Diffuse.b =   mCur->Radius/mCur->mPower /mCur->SmokeDiv ;
		prim->GetMaterial()->Ambient.b =  mCur->Radius/mCur->mPower /mCur->SmokeDiv ;
		prim->GetMaterial()->Specular.b =  mCur->Radius/mCur->mPower/mCur->SmokeDiv ;
		prim->GetMaterial()->Emissive.b =  mCur->Radius/mCur->mPower/mCur->SmokeDiv ;

		}

*/

}

	NoiseSphere* FractalTree::MakeNewExplosionNode(){
		NoiseSphere* s1 = new NoiseSphere();
		s1->center = D3DXVECTOR3(0,0,0);
		s1->radius = 0.0f;
		s1->radiusInner = 0.0f;
		s1->color = D3DCOLOR_XRGB(0,255,0);
		s1->ambientStrength = .3f;
		s1->diffuseColor = D3DCOLOR_XRGB(0,255,0);
		s1->diffuseStrength = .5f;
		s1->specularColor = D3DXCOLOR(255,255,255,255);	
		s1->specularStrength = .05f;
		s1->exponent = 100.0f;
		s1->shadingOn = true;	
		s1->reflection = 0.0f;
		s1->transmission = 0.0f;
		s1->ior = .95f;
		s1->softness = 1.0f;

		s1->diffuseColor.g = 0;
		s1->diffuseColor.r = 0;
		s1->diffuseColor.b = 0;
		s1->specularColor.g =0;
		s1->specularColor.r = 0;
		s1->specularColor.b = 0;
				
		return s1;
	}

	NoiseSphere* FractalTree::GetPrimitives(int* size){
		
		*size = mNodes->size();
		NoiseSphere* mPrims = new NoiseSphere[*size];
		for(int i =0; i < *size;i++){
			mPrims[i] = *(mNodes->at(i)->Sphere);
		}

		return mPrims;
	}

